package BO;

import DB.*;
import UI.*;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.persistence.*;

public class Service {

    private static final long milli = 21600000; //6timmar i millisekunder
    private static EntityManagerFactory fac = Persistence.createEntityManagerFactory("RomaCommunityv1PU");
    private static EntityManager manager = fac.createEntityManager();

    public Service() {
    }

    //Testfunktion
    public static void testBla() {
        Date d = new Date((new Date().getTime() - milli));
        try {
            Query q = manager.createQuery("Select c from ChatMessage c where c.timesent > :input").setParameter("input", d);
            List<StatusMessage> lista = q.getResultList();
            String o = "";
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static boolean removeFriendship(int req, int rec) {
        try {
            User requester = manager.find(User.class, req);
            User receiver = manager.find(User.class, rec);

            Collection<User> reqFriends = requester.getUserCollection();
            reqFriends.remove(receiver);
            requester.setUserCollection(reqFriends);

            Collection<User> recFriends = receiver.getUserCollection();
            recFriends.remove(requester);
            receiver.setUserCollection(recFriends);

            manager.getTransaction().begin();
            manager.merge(requester);
            manager.merge(receiver);
            manager.flush();
            manager.clear();
            manager.getTransaction().commit();
            return true;

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static List<StatusUI> getFriendStatusUpdates(int id) {
        List<StatusUI> returnList = new ArrayList<StatusUI>();
        try {
            User user = manager.find(User.class, id);
            Collection<StatusMessage> tempList;
            int i = 0;

            for (User tempUser : user.getUserCollection()) {
                i = 0;
                for (StatusMessage m : tempUser.getStatusMessageCollection()) {
                    returnList.add(new StatusUI(m.getText(), m.getTmeposted(), tempUser.getId(), tempUser.getName()));
                    if (i++ >= 5) {
                        break;
                    }
                }
            }
            Collections.sort(returnList, new StatusUIComparator());
            return returnList;
        } catch (Exception e) {
            e.printStackTrace();
            return returnList;
        }
    }

    public static List<UserUI> getUserFriends(int userId) {
        List<UserUI> friends = new ArrayList<UserUI>();
        try {
            User user = manager.find(User.class, userId);

            for (User friend : user.getUserCollection()) {
                friends.add(new UserUI(friend.getId(), friend.getName(), friend.getEmail()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return friends;
    }

    public static boolean addFriendship(int requester, int receiver) {

        if (requester != receiver) {
            try {
                User reqUser = manager.find(User.class, requester);
                User recUser = manager.find(User.class, receiver);

                Collection<User> uC1 = reqUser.getUserCollection();
                uC1.add(recUser);
                reqUser.setUserCollection(uC1);

                Collection<User> uC2 = recUser.getUserCollection();
                uC2.add(reqUser);
                recUser.setUserCollection(uC2);

                manager.getTransaction().begin();
                manager.merge(reqUser);
                manager.merge(recUser);
                manager.flush();
                manager.clear();
                manager.getTransaction().commit();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    public static List<PMUI> getReceivedPrivateMessages(UserUI user) {
        User u = manager.find(User.class, user.getId());
        List<PMUI> messages = new ArrayList<PMUI>();

        for (PrivateMessage m : u.getPrivateMessageCollectionReceiver()) {
            PMUI message = new PMUI();
            message.setSender(m.getSender().getName());
            message.setTimesent(m.getTimesent());
            message.setMessage(m.getMessage());
            message.setReceiver(m.getReceiver().getName());

            messages.add(message);
        }
        return messages;
    }

    public static List<PMUI> getSentPrivateMessages(UserUI user) {
        User u = manager.find(User.class, user.getId());
        List<PMUI> messages = new ArrayList<PMUI>();

        for (PrivateMessage m : u.getPrivateMessageCollectionSender()) {
            PMUI message = new PMUI();
            message.setSender(m.getSender().getName());
            message.setTimesent(m.getTimesent());
            message.setMessage(m.getMessage());
            message.setReceiver(m.getReceiver().getName());
            messages.add(message);
        }
        return messages;
    }

    public static boolean addInterest(int id, String newInterest) {
        try {
            User u = manager.find(DB.User.class, id);
            Query iQ = manager.createNamedQuery("Interest.findByName");
            iQ.setParameter("name", newInterest);

            Interest interest;

            try {
                interest = (Interest) iQ.getSingleResult();
            } catch (Exception e1) {
                interest = new Interest(newInterest);
            }

            Collection<Interest> userInterests = u.getInterestCollection();
            userInterests.add(interest);
            Collection<User> interestUsers = interest.getUserCollection();
            interestUsers.add(u);
            manager.getTransaction().begin();
            manager.merge(u);
            manager.merge(interest);
            manager.flush();
            manager.clear();
            manager.getTransaction().commit();
            return true;

        } catch (Exception e2) {
            return false;
        }
    }

    public static List<String> getUserNamesLike(String query) {
        List<String> list = new ArrayList<String>();

        Query q = manager.createQuery("Select u from User u where u.name like '%" + query + "%'");
        List<User> users = q.getResultList();
        for (User user : users) {
            list.add(user.getName());

        }

        return list;
    }

    public static List<InterestUI> getUserInterests(int userId) {
        List<InterestUI> interests = new ArrayList<InterestUI>();
        try {
            User u = manager.find(DB.User.class, userId);
            for (Interest i : u.getInterestCollection()) {
                interests.add(new InterestUI(i.getId(), i.getName()));
            }
            return interests;
        } catch (Exception e) {
            e.printStackTrace();
            return interests;
        }
    }

    public static boolean sendPrivateMessage(String receivername, String message, int id) {

        try {
            manager.getTransaction().begin();


            User sender = manager.find(User.class, id);
            Query query = manager.createNamedQuery("User.findByName");
            query.setParameter("name", receivername);
            User receiver = (User) query.getSingleResult();
            Collection<PrivateMessage> privateMessagesReceiver = receiver.getPrivateMessageCollectionReceiver();
            Collection<PrivateMessage> privateMessagesSender = sender.getPrivateMessageCollectionSender();

            PrivateMessage pm = new PrivateMessage();
            pm.setMessage(message);
            pm.setReceiver(receiver);
            pm.setSender(sender);
            pm.setTimesent(new Date());

            privateMessagesReceiver.add(pm);
            privateMessagesSender.add(pm);
            receiver.setPrivateMessageCollectionReceiver(privateMessagesReceiver);
            sender.setPrivateMessageCollectionSender(privateMessagesSender);

            manager.persist(pm);
            manager.persist(sender);
            manager.persist(receiver);

            manager.flush();
            manager.clear();

            manager.getTransaction().commit();

            return true;

        } catch (Exception e) {
            return false;
        }
    }

    public static UI.ChatUI getChatByID(int id) {
        UI.ChatUI chatUI = null;
        try {
            Query q = manager.createNamedQuery("Chat.findById");
            q.setParameter("id", id);
            DB.Chat chat = (DB.Chat) q.getSingleResult();

            chatUI = new ChatUI(chat.getId(), chat.getName());
            ArrayList<UI.ChatMessageUI> list = new ArrayList<ChatMessageUI>();
            for (DB.ChatMessage message : chat.getChatMessageCollection()) {
                UI.ChatMessageUI temp = new ChatMessageUI(message.getMessage(), new UI.UserUI(message.getSenderId().getId(), message.getSenderId().getName(), message.getSenderId().getEmail()), message.getId(), message.getTimesent(), chatUI);
                list.add(temp);
            }
            chatUI.setMessages(list);


        } catch (Exception e) {
        }


        return chatUI;
    }

    public static boolean createChatMessage(int chatId, String message, int userId) {
        try {

            Query chatQ = manager.createNamedQuery("Chat.findById");
            chatQ.setParameter("id", chatId);

            Query userQ = manager.createNamedQuery("User.findById");
            userQ.setParameter("id", userId);

            DB.Chat chat = (DB.Chat) chatQ.getSingleResult();
            DB.User sender = (DB.User) userQ.getSingleResult();
            DB.ChatMessage messageDB = new DB.ChatMessage();
            messageDB.setMessage(message);
            messageDB.setSenderId(sender);
            messageDB.setTimesent(new Date());
            messageDB.setChatid(chat);
            Collection<ChatMessage> msg = chat.getChatMessageCollection();
            msg.add(messageDB);
            chat.setChatMessageCollection(msg);
            manager.getTransaction().begin();
            manager.persist(messageDB);
            manager.persist(chat);
            manager.flush();
            manager.clear();
            manager.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }

    public static UserUI registerUser(String name, String email, String password) {
        UserUI user = null;
        if (name == null || name.isEmpty() || email == null || email.isEmpty() || password == null || password.isEmpty()) {
            return null;
        }
        try {
            Query q = manager.createNamedQuery("User.findByName");
            q.setParameter("name", name);
            if (q.getResultList().size() > 0) {
                return null;
            }

            String salt = UUID.randomUUID().toString();
            String passwordsalt = password + salt;
            MessageDigest digest = MessageDigest.getInstance("MD5");
            byte[] bytes = digest.digest(passwordsalt.getBytes());
            String hashPass = new String(bytes);

            EntityTransaction t = manager.getTransaction();
            t.begin();
            DB.User u = new DB.User(name, email, hashPass, salt);
            manager.persist(u);
            t.commit();
            user = new UserUI(u.getId(), u.getName(), u.getEmail());
            return user;
        } catch (Exception e) {
            e.printStackTrace();
            return user;
        }
    }

    public static UserUI validateUser(String name, String password) {
        UserUI user = null;
        try {

            Query q = manager.createNamedQuery("User.findByName");
            q.setParameter("name", name);
            DB.User u = (DB.User) q.getSingleResult();
            u.getPassword();
            String saltedpassword = password + u.getSalt();

            MessageDigest digest = MessageDigest.getInstance("MD5");
            byte[] bytes = digest.digest(saltedpassword.getBytes());
            String md5Password = new String(bytes);

            if (u.getPassword().equals(md5Password)) {
                user = new UserUI(u.getId(), u.getName(), u.getEmail());
                Login login = new Login();
                login.setLogontime(new Date());
                Collection<Login> logins = u.getLoginCollection();
                logins.add(login);
                u.setLoginCollection(logins);
                login.setUserid1(u);
                manager.getTransaction().begin();
                manager.persist(u);
                manager.persist(login);
                manager.flush();
                manager.clear();
                manager.getTransaction().commit();
            }


        } catch (Exception e) {
        }

        return user;
    }

    public static ArrayList<StatusUI> getStatusUpdates(int id) {
        try {
            User u = manager.find(DB.User.class, id);
            ArrayList<StatusUI> msgs = new ArrayList<StatusUI>();
            for (StatusMessage m : u.getStatusMessageCollection()) {
                msgs.add(new StatusUI(m.getText(), m.getTmeposted()));
            }
            manager.clear();
            return msgs;
        } catch (Exception e) {
            return new ArrayList<StatusUI>();
        }
    }

    public static boolean addStatusMessage(int id, String statusMessage) {
        try {
            User u = manager.find(DB.User.class, id);
            StatusMessage msg = new StatusMessage(statusMessage, new Date(), u);
            Collection<StatusMessage> m = u.getStatusMessageCollection();
            m.add(msg);
            u.setStatusMessageCollection(m);
            manager.getTransaction().begin();
            manager.merge(u);
            manager.merge(msg);
            manager.flush();
            manager.clear();
            manager.getTransaction().commit();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static UserUI getUser(int id) {
        try {
            User u = manager.find(DB.User.class, id);
            UserUI user = new UserUI(id, u.getName(), u.getEmail());
            List<StatusUI> status = new ArrayList<StatusUI>();

            for (StatusMessage m : u.getStatusMessageCollection()) {
                status.add(new StatusUI(m.getText(), m.getTmeposted()));
            }
            user.setStatusUpdates(status);
            return user;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static List<UserUI> searchAfterUser(String search) {
        List<User> queryList = new ArrayList<User>();
        List<UserUI> resultList = new ArrayList<UserUI>();

        try {
            Query q = manager.createQuery("Select u from User u where u.name like '%" + search + "%'");
            queryList = q.getResultList();
            for (User u : queryList) {
                resultList.add(new UserUI(u.getId(), u.getName(), u.getEmail()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultList;
    }
}
